#include <iostream>
#include <fstream>
#include <vector>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>//srand(),rand()

using namespace std;

//最终需要和单个缓存的搬运效率做比较

const int DATALEN = 100000;
const int BUFSIZE = 5;
const int DEBUG = 0;

//std::vector<int> data(DATALEN, 0);
std::vector<int> buf1(BUFSIZE, 0);
std::vector<int> buf2(BUFSIZE, 0);

/*将数据从内存向磁盘搬运*/
pthread_cond_t bufisempty1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t bufisempty2 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
bool isempty1 = true;
bool isempty2 = true;

int one_buf_test ();
int data_order_test (const char * filename);
void * one_buf_consumer(void *p);

void *consumer(void *p)
{
        int oldstate, oldtype;
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
	fstream tmpfile ("tmp.data", ios::out /*| ios::app*/ | ios::binary );
	vector<int>::iterator pit;
	bool switchbuf = false;
	for (;;) {
		
		//通过switchbuf保证搬运的顺序
		if ( switchbuf )
		{
			//cout << "cycle in consumer will lock buf2." << endl;

			//如果缓存2非空
			pthread_mutex_lock(&lock2);
			if ( false == isempty2 )
			{
				//一次性向磁盘写入BUFSIZE个元素
				for (pit = buf2.begin(); pit != buf2.end(); pit++)
				{
					tmpfile << *pit << endl;
				}
				//cout << "Consume 2 " << endl;
				switchbuf = false;
				isempty2 = true;
			}
			pthread_mutex_unlock(&lock2);
			pthread_cond_signal(&bufisempty2);
		}
		else
		{
			//cout << "cycle in consumer will lock buf1." << endl;

			//如果缓存1非空
			pthread_mutex_lock(&lock1);
			if ( false == isempty1 )
			{
				//一次性向磁盘写入BUFSIZE个元素
				for (pit = buf1.begin(); pit != buf1.end(); pit++)
				{
					tmpfile << *pit << endl;
				}
				//cout << "Consume 1 " << endl;
				switchbuf = true;
				isempty1 = true;
			}
			pthread_mutex_unlock(&lock1);
			pthread_cond_signal(&bufisempty1);
		}
	}//end of cycle
	//tmpfile.close();
}


int main ()
{
	pthread_t cid;

	srand(time(NULL));
	vector<int>::iterator it;

///*
	pthread_create(&cid, NULL, consumer, NULL);

	bool switchbuf = false;
	for ( int i = 0; i < DATALEN; ) {

		//通过switchbuf保证写入的顺序（哪空放哪，在内存速度慢的情况下顺序无法保证）
		if ( switchbuf )
		{
			//cout << "cycle in produce will lock buf2." << endl;

			pthread_mutex_lock(&lock2);
			//当缓存2非空
			while ( false == isempty2 )
			{
				//cout << "2 wait ..." << endl;
				pthread_cond_wait(&bufisempty2, &lock2);
			}
			//一次性向内存写入BUFSIZE个元素
			for (it = buf2.begin(); it != buf2.end(); it++)
			{
				*it = i++;
			}
			//cout << "Produce 2 " << endl;
			switchbuf = false;
			isempty2 = false;
			pthread_mutex_unlock(&lock2);
		}
		else
		{
			//cout << "cycle in produce will lock buf1." << endl;

			pthread_mutex_lock(&lock1);
			//当缓存1非空
			while ( false == isempty1 )
			{
				//cout << "1 wait ..." << endl;
				pthread_cond_wait(&bufisempty1, &lock1);
			}
			//一次性向内存写入BUFSIZE个元素
			for (it = buf1.begin(); it != buf1.end(); it++)
			{
				*it = i++;
			}
			//cout << "Produce 1 " << endl;
			switchbuf = true;
			isempty1 = false;
			pthread_mutex_unlock(&lock1);
		}
	}
	sleep (1);
	pthread_cancel(cid);
	pthread_join(cid, NULL);
	data_order_test("tmp.data");

//*/

/*
	//one_buf_test();
	isempty1 = true;
	pthread_create(&cid, NULL, one_buf_consumer, NULL);

	for ( int i = 0; i < DATALEN;  ) {

		//cout << "cycle in produce try to lock buf1." << endl;

		pthread_mutex_lock(&lock1);
		if ( isempty1 )
		{
			//一次性向内存写入BUFSIZE个元素
			for (it = buf1.begin(); it != buf1.end(); it++)
			{
				*it = i++;
			}
			//cout << "Produce 1 " << endl;
			isempty1 = false;
		}
		pthread_mutex_unlock(&lock1);
	}

	sleep (1);
	pthread_cancel(cid);
	pthread_join(cid, NULL);
	data_order_test("tmp.data.one.buf");
//*/

	return 0;
}//end of main


void * one_buf_consumer(void *p)
{
        int oldstate, oldtype;
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
	fstream tmpfile ("tmp.data.one.buf", ios::out /*| ios::app*/ | ios::binary );
	vector<int>::iterator oit;
	for (;;) {

		//cout << "cycle in consumer try to lock buf1." << endl;

		pthread_mutex_lock(&lock1);
		//如果缓存1非空
		if ( false == isempty1 )
		{
			//一次性向磁盘写入BUFSIZE个元素
			for (oit = buf1.begin(); oit != buf1.end(); oit++)
			{
				tmpfile << *oit << endl;
				//*oit = 0;
			}
			//cout << "Consume 1 " << endl;
			isempty1 = true;
		}
		pthread_mutex_unlock(&lock1);
	}
	tmpfile.close();
}//end of one_buf_consumer


int one_buf_test ()
{
	pthread_t cid;

	vector<int>::iterator it;
	pthread_create(&cid, NULL, one_buf_consumer, NULL);

	for ( int i = 0; i < DATALEN;  ) {

		//cout << "cycle in produce try to lock buf1." << endl;

		pthread_mutex_lock(&lock1);
		if ( isempty1 )
		{
			//一次性向内存写入BUFSIZE个元素
			for (it = buf1.begin(); it != buf1.end(); it++)
			{
				*it = i++;
			}
			//cout << "Produce 1 " << endl;
			isempty1 = false;
		}
		pthread_mutex_unlock(&lock1);
	}

	sleep (1);
	pthread_cancel(cid);
	pthread_join(cid, NULL);
	return 0;

}//end of one_buf_test


int data_order_test (const char * filename)
{
	fstream tmpfile (filename, ios::in /*| ios::app*/ );
	int i = 0, tmp;
	bool ordered = true;
	while ( !tmpfile.eof() )
	{
		tmpfile >> dec >> tmp;
		//cout << tmp << "	" << sizeof (tmp) << endl;
		if ( i++ != tmp )
		{
			ordered = false;
			break;
		}
		tmp = -1;
	}
	if (ordered)
	{
		cout << filename << " order is right." << endl;
	}
	else
	{
		cout << filename << " order is not right at " << i << " line " << tmp << endl;
	}
	tmpfile.close();
	return 0;
}

